﻿using Prism.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IV.Event
{
    public class EventAggregator
    {
        protected EventAggregator()
        {

        }
        /// <summary>
        /// 订阅事件
        /// </summary>
        /// <typeparam name="TPayload"></typeparam>
        /// <param name="action"></param>
        /// <param name="IsBackground">True:订阅事件回调与发布者在不同的线程</param>
        /// <param name="IsKeepAlive"></param>
        public static SubscriptionToken Subscribe<TPayload>(Action<TPayload> action, bool IsBackground = false, bool IsKeepAlive = false)
        {
            var e = GetEvent<PubSubEvent<TPayload>>();
            return e.Subscribe(action, IsBackground ? ThreadOption.BackgroundThread : ThreadOption.PublisherThread, IsKeepAlive);
        }
        public static SubscriptionToken Subscribe<TPayload>(Action<TPayload> action, Predicate<TPayload> filter, bool IsBackground =false, bool IsKeepAlive = false)
        {
            var e = GetEvent<PubSubEvent<TPayload>>();
            return e.Subscribe(action, IsBackground ? ThreadOption.BackgroundThread : ThreadOption.PublisherThread, IsKeepAlive, filter);
        }
        /// <summary>
        /// 发布事件
        /// </summary>
        /// <typeparam name="TPayload"></typeparam>
        /// <param name="payload"></param>
        public static void Publish<TPayload>(TPayload payload)
        {
            var e = GetEvent<PubSubEvent<TPayload>>();
            e.Publish(payload);
        }

        /// <summary>
        /// 异步的Publish
        /// </summary>
        /// <typeparam name="TPayload"></typeparam>
        /// <param name="payload"></param>
        /// <returns></returns>
        public static Task PublishAsync<TPayload>(TPayload payload)
        {
            return Task.FromResult(Task.Run(() =>
            {
                var e = GetEvent<PubSubEvent<TPayload>>();
                e.Publish(payload);
            }));
        }
        /// <summary>
        /// 取消事件订阅
        /// </summary>
        /// <typeparam name="TPayload"></typeparam>
        /// <param name="token"></param>
        public static void Unsubscribe<TPayload>(SubscriptionToken token)
        {
            var e = GetEvent<PubSubEvent<TPayload>>();
            e.Unsubscribe(token);
        }

        private static readonly Dictionary<Type, EventBase> events = new Dictionary<Type, EventBase>();
        private static TEventType GetEvent<TEventType>() where TEventType : EventBase, new()
        {
            lock (events)
            {
                EventBase existingEvent = null;
                if (!events.TryGetValue(typeof(TEventType), out existingEvent))
                {
                    TEventType newEvent = new TEventType();
                    events[typeof(TEventType)] = newEvent;
                    return newEvent;
                }
                else
                {
                    return (TEventType)existingEvent;
                }
            }
        }

    }
}
